home *** CD-ROM | disk | FTP | other *** search
/ Aminet 51 / Aminet 51 (2002)(GTI - Schatztruhe)[!][Oct 2002].iso / Aminet / util / arc / xadmasterdev.lha / xad / Sources / clients / LZX.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-08-20  |  25.4 KB  |  963 lines

  1. #ifndef XADMASTER_LZX_C
  2. #define XADMASTER_LZX_C
  3.  
  4. /* Programmheader
  5.  
  6.     Name:        LZX.c
  7.     Main:        xadmaster
  8.     Versionstring:    $VER: LZX.c 1.9 (30.01.2002)
  9.     Author:        SDI, David Tritscher
  10.     Distribution:    Freeware
  11.     Description:    LZX file archiver client
  12.  
  13.  1.0   09.02.99 : first working version
  14.  1.1   13.03.99 : now uses register parameters
  15.  1.2   20.06.99 : removed exec.library calls
  16.  1.3   29.06.99 : now uses master free stuff
  17.  1.4   29.08.99 : uses ConvertE.c instead of own routines and
  18.     uses crc copy function
  19.  1.5   02.01.00 : now library version 4 client
  20.  1.6   09.03.00 : now library version 6 client
  21.  1.7   02.10.00 : added check for different CPU's
  22.  1.8   14.07.01 : added xadAddFileEntry method
  23.  1.9   30.01.02 : fixed date problem a bit
  24. */
  25.  
  26. /* The decrunch routines of this client are based on unlzx sources code made
  27.    by David Tritscher. Thanks guy, was a big help. I made the routines
  28.    reentrant (using a parameter structure) and developed the XAD interface
  29.    functions. */
  30.  
  31. #include <proto/xadmaster.h>
  32. #include <exec/memory.h>
  33. #include <dos/dos.h>
  34. #include "SDI_compiler.h"
  35. #define SDI_TO_ANSI
  36. #include "SDI_ASM_STD_protos.h"
  37. #include "ConvertE.c"
  38. #include "xadCPU.h"
  39.  
  40. #ifndef XADMASTERFILE
  41. #define LZX_Client        FirstClient
  42. #define NEXTCLIENT        0
  43. #define XADMASTERVERSION    10
  44. UBYTE version[] = "$VER: LZX 1.9 (30.01.2002)" CPUTEXT " Freeware by Dirk Stöcker";
  45. #endif
  46. #define LZX_VERSION        1
  47. #define LZX_REVISION        9
  48.  
  49. /* ---------------------------------------------------------------------- */
  50.  
  51. #define LZXINFO_DAMAGE_PROTECT 1
  52. #define LZXINFO_FLAG_LOCKED 2
  53.  
  54. struct LZXInfo_Header
  55. {
  56.   UBYTE ID[3];            /* "LZX" */
  57.   UBYTE Flags;            /* LZXINFO_FLAG_#? */
  58.   UBYTE Unknown[6];        
  59. };
  60.  
  61. #define LZXHDR_FLAG_MERGED    (1<<0)
  62.  
  63. #define LZXHDR_PROT_READ    (1<<0)
  64. #define LZXHDR_PROT_WRITE    (1<<1)
  65. #define LZXHDR_PROT_DELETE    (1<<2)
  66. #define LZXHDR_PROT_EXECUTE    (1<<3)
  67. #define LZXHDR_PROT_ARCHIVE    (1<<4)
  68. #define LZXHDR_PROT_HOLD    (1<<5)
  69. #define LZXHDR_PROT_SCRIPT    (1<<6)
  70. #define LZXHDR_PROT_PURE    (1<<7)
  71.  
  72. #define LZXHDR_TYPE_MSDOS    0
  73. #define LZXHDR_TYPE_WINDOWS    1
  74. #define LZXHDR_TYPE_OS2        2
  75. #define LZXHDR_TYPE_AMIGA    10
  76. #define LZXHDR_TYPE_UNIX    20
  77.  
  78. #define LZXHDR_PACK_STORE    0
  79. #define LZXHDR_PACK_NORMAL    2
  80. #define LZXHDR_PACK_EOF        32
  81.  
  82. struct LZXArc_Header
  83. {
  84.   UBYTE Attributes;        /*  0 - LZXHDR_PROT_#? */
  85.   UBYTE pad1;            /*  1 */
  86.   UBYTE FileSize[4];        /*  2 (little endian) */
  87.   UBYTE CrSize[4];        /*  6 (little endian) */
  88.   UBYTE MachineType;        /* 10 - LZXHDR_TYPE_#? */
  89.   UBYTE PackMode;        /* 11 - LZXHDR_PACK_#? */
  90.   UBYTE Flags;            /* 12 - LZXHDR_FLAG_#? */
  91.   UBYTE pad2;            /* 13 */
  92.   UBYTE CommentSize;        /* 14 - length (0-79) */
  93.   UBYTE ExtractVersion;        /* 15 - version needed to extract */
  94.   UBYTE pad3;            /* 16 */
  95.   UBYTE pad4;            /* 17 */
  96.   UBYTE Date[4];        /* 18 - Packed_Date */
  97.   UBYTE DataCRC[4];        /* 22 (little endian) */
  98.   UBYTE HeaderCRC[4];        /* 26 (little endian) */
  99.   UBYTE FilenameSize;        /* 30 - filename length */
  100. }; /* SIZE = 31 */
  101.  
  102. /* Header CRC includes filename and comment. */
  103.  
  104. #define LZXHEADERSIZE    31
  105.  
  106. /* Packed date [4 BYTES, bit 0 is MSB, 31 is LSB]
  107.   bit  0 -  4    Day
  108.        5 -  8    Month    (January is 0)
  109.        9 - 14    Year    (start 1970)
  110.       15 - 19    Hour
  111.       20 - 25    Minute
  112.       26 - 31    Second
  113. */
  114.  
  115. struct LZXEntryData {
  116.   ULONG CRC;        /* CRC of uncrunched data */
  117.   ULONG PackMode;    /* CrunchMode */
  118.   ULONG ArchivePos;    /* Position is source file */
  119.   ULONG DataStart;    /* Position in merged buffer */
  120. };
  121.  
  122. #define LZXPE(a)    ((struct LZXEntryData *) ((a)->xfi_PrivateInfo))
  123. #define LZXDD(a)    ((struct LZXDecrData *) ((a)->xai_PrivateClient))
  124. struct LZXDecrData {
  125.   ULONG ArchivePos;    /* The Archive-Pos to detect if it is correct buffer */
  126.   ULONG DataPos;    /* must be lower or equal to current entry or reinit is necessary */
  127.  
  128.   UBYTE *source;
  129.   UBYTE *destination;
  130.   UBYTE *source_end;
  131.   UBYTE *destination_end;
  132.   UBYTE *pos;
  133.  
  134.   ULONG decrunch_method;
  135.   ULONG decrunch_length;
  136.   ULONG pack_size;
  137.   ULONG last_offset;
  138.   ULONG control;
  139.   LONG  shift;
  140.  
  141.   UBYTE offset_len[8];
  142.   UWORD offset_table[128];
  143.   UBYTE huffman20_len[20];
  144.   UWORD huffman20_table[96];
  145.   UBYTE literal_len[768];
  146.   UWORD literal_table[5120];
  147.  
  148.   UBYTE read_buffer[16384];        /* have a reasonable sized read buffer */
  149.   UBYTE decrunch_buffer[258+65536+258];    /* allow overrun for speed */
  150. };
  151.  
  152. ASM(BOOL) LZX_RecogData(REG(d0, ULONG size), REG(a0, STRPTR data),
  153. REG(a6, struct xadMasterBase *xadMasterBase))
  154. { CPUCHECK
  155.   if(data[0] == 'L' && data[1] == 'Z' && data[2] == 'X')
  156.     return 1;
  157.   else
  158.     return 0;
  159. }
  160.  
  161. ASM(LONG) LZX_GetInfo(REG(a0, struct xadArchiveInfo *ai),
  162. REG(a6, struct xadMasterBase *xadMasterBase))
  163. {
  164.   LONG err;
  165.   ULONG bufpos = 0;
  166.   struct xadFileInfo *fi, *fig = 0; /* fig - first grouped ptr */
  167.   struct LZXArc_Header head;
  168.  
  169.   if(!(err = xadHookAccess(XADAC_INPUTSEEK, sizeof(struct LZXInfo_Header), 0, ai)))
  170.   {
  171.     while(!err && ai->xai_InPos < ai->xai_InSize)
  172.     {
  173.       if(!(err = xadHookAccess(XADAC_READ, LZXHEADERSIZE, &head, ai)))
  174.       {
  175.     ULONG i, j, k, l, crc;
  176.         i = head.CommentSize;
  177.         j = head.FilenameSize;
  178.         k = EndGetI32(head.HeaderCRC);
  179.         head.HeaderCRC[0] = head.HeaderCRC[1] = head.HeaderCRC[2] = head.HeaderCRC[3] = 0;
  180.         /* clear for CRC check */
  181.  
  182.         if(!(fi = (struct xadFileInfo *) xadAllocObject(XADOBJ_FILEINFO,
  183.         XAD_OBJNAMESIZE, j+1, i ? XAD_OBJCOMMENTSIZE : TAG_IGNORE, i+1,
  184.         XAD_OBJPRIVINFOSIZE, sizeof(struct LZXEntryData), TAG_DONE)))
  185.           err = XADERR_NOMEMORY;
  186.         else if(!(err = xadHookAccess(XADAC_READ, j, fi->xfi_FileName, ai)) &&
  187.         (!i || !(err = xadHookAccess(XADAC_READ, i, fi->xfi_Comment, ai))))
  188.         {
  189.           l = EndGetI32(head.CrSize);
  190.  
  191.           if(!l || !(err = xadHookAccess(XADAC_INPUTSEEK, l, 0, ai)))
  192.           {
  193.             crc = xadCalcCRC32(XADCRC32_ID1, ~0, LZXHEADERSIZE, (STRPTR) &head);
  194.             crc = xadCalcCRC32(XADCRC32_ID1, crc, j, fi->xfi_FileName);
  195.             if(i)
  196.               crc = xadCalcCRC32(XADCRC32_ID1, crc, i, fi->xfi_Comment);
  197.  
  198.             if(~crc != k)
  199.               err = XADERR_CHECKSUM;
  200.             else
  201.             {
  202.               if(!fig)
  203.               {
  204.                 fig = fi; bufpos = 0;
  205.               }
  206.           fi->xfi_Size = EndGetI32(head.FileSize);
  207.           if(!l && !fi->xfi_Size && fi->xfi_FileName[--j] == '/')
  208.           {
  209.             fi->xfi_FileName[j] = 0;
  210.             fi->xfi_Flags |= XADFIF_DIRECTORY;
  211.           }
  212.  
  213.           i = head.Attributes;
  214.           j = 0;
  215.  
  216.           if(!(i & LZXHDR_PROT_READ))
  217.             j |= FIBF_READ;
  218.           if(!(i & LZXHDR_PROT_WRITE))
  219.             j |= FIBF_WRITE;
  220.           if(!(i & LZXHDR_PROT_DELETE))
  221.             j |= FIBF_DELETE;
  222.           if(!(i & LZXHDR_PROT_EXECUTE))
  223.             j |= FIBF_EXECUTE;
  224.           j |= (i & (LZXHDR_PROT_ARCHIVE|LZXHDR_PROT_SCRIPT));
  225.           if(i & LZXHDR_PROT_PURE)
  226.             j |= FIBF_PURE;
  227.           if(i & LZXHDR_PROT_HOLD)
  228.             j |= (1<<7);    /* not defined in <dos/dos.h> */
  229.           fi->xfi_Protection = j;
  230.  
  231.           { /* Make the date */
  232.             struct xadDate d;
  233.             j = EndGetM32(head.Date);
  234.             d.xd_Second = j & 63;
  235.             j >>= 6;
  236.             d.xd_Minute = j & 63;
  237.             j >>= 6;
  238.             d.xd_Hour = j & 31;
  239.             j >>= 5;
  240.             d.xd_Year = 1970 + (j & 63);
  241.             if(d.xd_Year >= 2028)      /* Original LZX */
  242.               d.xd_Year += 2000-2028;
  243.             else if(d.xd_Year < 1978) /* Dr.Titus */
  244.               d.xd_Year += 2034-1970;
  245.             /* Dates from 1978 to 1999 are correct */
  246.             /* Dates from 2000 to 2027 Mikolaj patch are correct */
  247.             /* Dates from 2000 to 2005 LZX/Dr.Titus patch are correct */
  248.             /* Dates from 2034 to 2041 Dr.Titus patch are correct */
  249.             j >>= 6;
  250.             d.xd_Month = 1 + (j & 15);
  251.             j >>= 4;
  252.             d.xd_Day = j;
  253.             d.xd_Micros = 0;
  254.                 xadConvertDates(XAD_DATEXADDATE, &d, XAD_GETDATEXADDATE,
  255.                 &fi->xfi_Date, TAG_DONE);
  256.           }
  257.           LZXPE(fi)->CRC = EndGetI32(head.DataCRC);
  258.           LZXPE(fi)->DataStart = bufpos;
  259.           bufpos += fi->xfi_Size;
  260.           if(head.Flags & LZXHDR_FLAG_MERGED)
  261.           {
  262.             fi->xfi_Flags |= XADFIF_GROUPED;
  263.             if(l)
  264.             {
  265.               fi->xfi_Flags |= XADFIF_ENDOFGROUP;
  266.               fi->xfi_GroupCrSize = l;
  267.             }
  268.           }
  269.           else
  270.             fi->xfi_CrunchSize = l;
  271.           
  272.           if(l)
  273.           {
  274.             LZXPE(fi)->ArchivePos = ai->xai_InPos-l;
  275.             LZXPE(fi)->PackMode = head.PackMode;
  276.             while(fig)
  277.             {
  278.               fig->xfi_GroupCrSize = l;
  279.               LZXPE(fig)->ArchivePos = ai->xai_InPos-l;
  280.               LZXPE(fig)->PackMode = head.PackMode;
  281.                   fig = fig->xfi_Next;
  282.                 }
  283.               }
  284.  
  285.               err = xadAddFileEntryA(fi, ai, 0);
  286.               fi = 0;
  287.             } /* skip crunched data */
  288.           } /* get filename and comment */
  289.           if(fi)
  290.             xadFreeObjectA(fi,0);
  291.         } /* xadFileInfo Allocation */
  292.       } /* READ header */
  293.     } /* while loop */
  294.   } /* INPUTSEEK 3 bytes */
  295.  
  296.   if(err && ai->xai_FileInfo)
  297.   {
  298.     ai->xai_Flags |= XADAIF_FILECORRUPT;
  299.     ai->xai_LastError = err;
  300.     err = 0;
  301.   }
  302.  
  303.   return err;
  304. }
  305.  
  306. /* ---------------------------------------------------------------------- */
  307.  
  308. static const UBYTE LZXtable_one[32] = {
  309.   0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,14,14
  310. };
  311.  
  312. static const ULONG LZXtable_two[32] = {
  313.   0,1,2,3,4,6,8,12,16,24,32,48,64,96,128,192,256,384,512,768,1024,
  314.   1536,2048,3072,4096,6144,8192,12288,16384,24576,32768,49152,
  315. };
  316.  
  317. static const UWORD LZXmask_bits[16] = {
  318.   0x0000,0x0001,0x0003,0x0007,0x000F,0x001F,0x003F,0x007F,
  319.   0x00FF,0x01FF,0x03FF,0x07FF,0x0FFF,0x1FFF,0x3FFF,0x7FFF,
  320. };
  321.  
  322. static const UBYTE LZXtable_four[34] = {
  323.   0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,
  324.   0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16
  325. };
  326.  
  327. /* ---------------------------------------------------------------------- */
  328.  
  329. /* Build a fast huffman decode table from the symbol bit lengths.         */
  330. /* There is an alternate algorithm which is faster but also more complex. */
  331.  
  332. static LONG LZXmake_decode_table(LONG number_symbols, LONG LZXtable_size,
  333.                       UBYTE *length, unsigned short *table)
  334. {
  335.  register UBYTE bit_num = 0;
  336.  register LONG symbol;
  337.  ULONG leaf; /* could be a register */
  338.  ULONG LZXtable_mask, bit_mask, pos, fill, next_symbol, reverse;
  339.  LONG abort = 0;
  340.  
  341.  pos = 0; /* consistantly used as the current position in the decode table */
  342.  
  343.  bit_mask = LZXtable_mask = 1 << LZXtable_size;
  344.  
  345.  bit_mask >>= 1; /* don't do the first number */
  346.  bit_num++;
  347.  
  348.  while((!abort) && (bit_num <= LZXtable_size))
  349.  {
  350.   for(symbol = 0; symbol < number_symbols; symbol++)
  351.   {
  352.    if(length[symbol] == bit_num)
  353.    {
  354.     reverse = pos; /* reverse the order of the position's bits */
  355.     leaf = 0;
  356.     fill = LZXtable_size;
  357.     do /* reverse the position */
  358.     {
  359.      leaf = (leaf << 1) + (reverse & 1);
  360.      reverse >>= 1;
  361.     } while(--fill);
  362.     if((pos += bit_mask) > LZXtable_mask)
  363.     {
  364.      abort = 1;
  365.      break; /* we will overrun the table! abort! */
  366.     }
  367.     fill = bit_mask;
  368.     next_symbol = 1 << bit_num;
  369.     do
  370.     {
  371.      table[leaf] = symbol;
  372.      leaf += next_symbol;
  373.     } while(--fill);
  374.    }
  375.   }
  376.   bit_mask >>= 1;
  377.   bit_num++;
  378.  }
  379.  
  380.  if((!abort) && (pos != LZXtable_mask))
  381.  {
  382.   for(symbol = pos; symbol < LZXtable_mask; symbol++) /* clear the rest of the table */
  383.   {
  384.    reverse = symbol; /* reverse the order of the position's bits */
  385.    leaf = 0;
  386.    fill = LZXtable_size;
  387.    do /* reverse the position */
  388.    {
  389.     leaf = (leaf << 1) + (reverse & 1);
  390.     reverse >>= 1;
  391.    } while(--fill);
  392.    table[leaf] = 0;
  393.   }
  394.   next_symbol = LZXtable_mask >> 1;
  395.   pos <<= 16;
  396.   LZXtable_mask <<= 16;
  397.   bit_mask = 32768;
  398.  
  399.   while((!abort) && (bit_num <= 16))
  400.   {
  401.    for(symbol = 0; symbol < number_symbols; symbol++)
  402.    {
  403.     if(length[symbol] == bit_num)
  404.     {
  405.      reverse = pos >> 16; /* reverse the order of the position's bits */
  406.      leaf = 0;
  407.      fill = LZXtable_size;
  408.      do /* reverse the position */
  409.      {
  410.       leaf = (leaf << 1) + (reverse & 1);
  411.       reverse >>= 1;
  412.      } while(--fill);
  413.      for(fill = 0; fill < bit_num - LZXtable_size; fill++)
  414.      {
  415.       if(table[leaf] == 0)
  416.       {
  417.        table[(next_symbol << 1)] = 0;
  418.        table[(next_symbol << 1) + 1] = 0;
  419.        table[leaf] = next_symbol++;
  420.       }
  421.       leaf = table[leaf] << 1;
  422.       leaf += (pos >> (15 - fill)) & 1;
  423.      }
  424.      table[leaf] = symbol;
  425.      if((pos += bit_mask) > LZXtable_mask)
  426.      {
  427.       abort = 1;
  428.       break; /* we will overrun the table! abort! */
  429.      }
  430.     }
  431.    }
  432.    bit_mask >>= 1;
  433.    bit_num++;
  434.   }
  435.  }
  436.  if(pos != LZXtable_mask) abort = 1; /* the table is incomplete! */
  437.  
  438.  return(abort);
  439. }
  440.  
  441. /* ---------------------------------------------------------------------- */
  442. /* Read and build the decrunch tables. There better be enough data in the */
  443. /* source buffer or it's stuffed. */
  444.  
  445. static LONG LZX_read_literal_table(struct LZXDecrData *decr)
  446. {
  447.  register ULONG control;
  448.  register LONG shift;
  449.  ULONG temp; /* could be a register */
  450.  ULONG symbol, pos, count, fix, max_symbol;
  451.  UBYTE *source;
  452.  LONG abort = 0;
  453.  
  454.  source = decr->source;
  455.  control = decr->control;
  456.  shift = decr->shift;
  457.  
  458.  if(shift < 0) /* fix the control word if necessary */
  459.  {
  460.   shift += 16;
  461.   control += *source++ << (8 + shift);
  462.   control += *source++ << shift;
  463.  }
  464.  
  465. /* read the decrunch method */
  466.  
  467.  decr->decrunch_method = control & 7;
  468.  control >>= 3;
  469.  if((shift -= 3) < 0)
  470.  {
  471.   shift += 16;
  472.   control += *source++ << (8 + shift);
  473.   control += *source++ << shift;
  474.  }
  475.  
  476. /* Read and build the offset huffman table */
  477.  
  478.  if((!abort) && (decr->decrunch_method == 3))
  479.  {
  480.   for(temp = 0; temp < 8; temp++)
  481.   {
  482.    decr->offset_len[temp] = control & 7;
  483.    control >>= 3;
  484.    if((shift -= 3) < 0)
  485.    {
  486.     shift += 16;
  487.     control += *source++ << (8 + shift);
  488.     control += *source++ << shift;
  489.    }
  490.   }
  491.   abort = LZXmake_decode_table(8, 7, decr->offset_len, decr->offset_table);
  492.  }
  493.  
  494. /* read decrunch length */
  495.  
  496.  if(!abort)
  497.  {
  498.   decr->decrunch_length = (control & 255) << 16;
  499.   control >>= 8;
  500.   if((shift -= 8) < 0)
  501.   {
  502.    shift += 16;
  503.    control += *source++ << (8 + shift);
  504.    control += *source++ << shift;
  505.   }
  506.   decr->decrunch_length += (control & 255) << 8;
  507.   control >>= 8;
  508.   if((shift -= 8) < 0)
  509.   {
  510.    shift += 16;
  511.    control += *source++ << (8 + shift);
  512.    control += *source++ << shift;
  513.   }
  514.   decr->decrunch_length += (control & 255);
  515.   control >>= 8;
  516.   if((shift -= 8) < 0)
  517.   {
  518.    shift += 16;
  519.    control += *source++ << (8 + shift);
  520.    control += *source++ << shift;
  521.   }
  522.  }
  523.  
  524. /* read and build the huffman literal table */
  525.  
  526.  if((!abort) && (decr->decrunch_method != 1))
  527.  {
  528.   pos = 0;
  529.   fix = 1;
  530.   max_symbol = 256;
  531.  
  532.   do
  533.   {
  534.    for(temp = 0; temp < 20; temp++)
  535.    {
  536.     decr->huffman20_len[temp] = control & 15;
  537.     control >>= 4;
  538.     if((shift -= 4) < 0)
  539.     {
  540.      shift += 16;
  541.      control += *source++ << (8 + shift);
  542.      control += *source++ << shift;
  543.     }
  544.    }
  545.    abort = LZXmake_decode_table(20, 6, decr->huffman20_len, decr->huffman20_table);
  546.  
  547.    if(abort) break; /* argh! table is corrupt! */
  548.  
  549.    do
  550.    {
  551.     if((symbol = decr->huffman20_table[control & 63]) >= 20)
  552.     {
  553.      do /* symbol is longer than 6 bits */
  554.      {
  555.       symbol = decr->huffman20_table[((control >> 6) & 1) + (symbol << 1)];
  556.       if(!shift--)
  557.       {
  558.        shift += 16;
  559.        control += *source++ << 24;
  560.        control += *source++ << 16;
  561.       }
  562.       control >>= 1;
  563.      } while(symbol >= 20);
  564.      temp = 6;
  565.     }
  566.     else
  567.     {
  568.      temp = decr->huffman20_len[symbol];
  569.     }
  570.     control >>= temp;
  571.     if((shift -= temp) < 0)
  572.     {
  573.      shift += 16;
  574.      control += *source++ << (8 + shift);
  575.      control += *source++ << shift;
  576.     }
  577.     switch(symbol)
  578.     {
  579.      case 17:
  580.      case 18:
  581.      {
  582.       if(symbol == 17)
  583.       {
  584.        temp = 4;
  585.        count = 3;
  586.       }
  587.       else /* symbol == 18 */
  588.       {
  589.        temp = 6 - fix;
  590.        count = 19;
  591.       }
  592.       count += (control & LZXmask_bits[temp]) + fix;
  593.       control >>= temp;
  594.       if((shift -= temp) < 0)
  595.       {
  596.        shift += 16;
  597.        control += *source++ << (8 + shift);
  598.        control += *source++ << shift;
  599.       }
  600.       while((pos < max_symbol) && (count--))
  601.        decr->literal_len[pos++] = 0;
  602.       break;
  603.      }
  604.      case 19:
  605.      {
  606.       count = (control & 1) + 3 + fix;
  607.       if(!shift--)
  608.       {
  609.        shift += 16;
  610.        control += *source++ << 24;
  611.        control += *source++ << 16;
  612.       }
  613.       control >>= 1;
  614.       if((symbol = decr->huffman20_table[control & 63]) >= 20)
  615.       {
  616.        do /* symbol is longer than 6 bits */
  617.        {
  618.         symbol = decr->huffman20_table[((control >> 6) & 1) + (symbol << 1)];
  619.         if(!shift--)
  620.         {
  621.          shift += 16;
  622.          control += *source++ << 24;
  623.          control += *source++ << 16;
  624.         }
  625.         control >>= 1;
  626.        } while(symbol >= 20);
  627.        temp = 6;
  628.       }
  629.       else
  630.       {
  631.        temp = decr->huffman20_len[symbol];
  632.       }
  633.       control >>= temp;
  634.       if((shift -= temp) < 0)
  635.       {
  636.        shift += 16;
  637.        control += *source++ << (8 + shift);
  638.        control += *source++ << shift;
  639.       }
  640.       symbol = LZXtable_four[decr->literal_len[pos] + 17 - symbol];
  641.       while((pos < max_symbol) && (count--))
  642.        decr->literal_len[pos++] = symbol;
  643.       break;
  644.      }
  645.      default:
  646.      {
  647.       symbol = LZXtable_four[decr->literal_len[pos] + 17 - symbol];
  648.       decr->literal_len[pos++] = symbol;
  649.       break;
  650.      }
  651.     }
  652.    } while(pos < max_symbol);
  653.    fix--;
  654.    max_symbol += 512;
  655.   } while(max_symbol == 768);
  656.  
  657.   if(!abort)
  658.    abort = LZXmake_decode_table(768, 12, decr->literal_len, decr->literal_table);
  659.  }
  660.  
  661.  decr->control = control;
  662.  decr->shift = shift;
  663.  decr->source = source;
  664.  return(abort);
  665. }
  666.  
  667. /* ---------------------------------------------------------------------- */
  668.  
  669. /* Fill up the decrunch buffer. Needs lots of overrun for both destination */
  670. /* and source buffers. Most of the time is spent in this routine so it's  */
  671. /* pretty damn optimized. */
  672. static void LZXdecrunch(struct LZXDecrData *decr)
  673. {
  674.  register ULONG control;
  675.  register LONG shift;
  676.  ULONG temp; /* could be a register */
  677.  ULONG symbol, count;
  678.  UBYTE *string, *source, *destination;
  679.  
  680.  control = decr->control;
  681.  shift = decr->shift;
  682.  source = decr->source;
  683.  destination = decr->destination;
  684.  
  685.  do
  686.  {
  687.   if((symbol = decr->literal_table[control & 4095]) >= 768)
  688.   {
  689.    control >>= 12;
  690.    if((shift -= 12) < 0)
  691.    {
  692.     shift += 16;
  693.     control += *source++ << (8 + shift);
  694.     control += *source++ << shift;
  695.    }
  696.    do /* literal is longer than 12 bits */
  697.    {
  698.     symbol = decr->literal_table[(control & 1) + (symbol << 1)];
  699.     if(!shift--)
  700.     {
  701.      shift += 16;
  702.      control += *source++ << 24;
  703.      control += *source++ << 16;
  704.     }
  705.     control >>= 1;
  706.    } while(symbol >= 768);
  707.   }
  708.   else
  709.   {
  710.    temp = decr->literal_len[symbol];
  711.    control >>= temp;
  712.    if((shift -= temp) < 0)
  713.    {
  714.     shift += 16;
  715.     control += *source++ << (8 + shift);
  716.     control += *source++ << shift;
  717.    }
  718.   }
  719.   if(symbol < 256)
  720.   {
  721.    *destination++ = symbol;
  722.   }
  723.   else
  724.   {
  725.    symbol -= 256;
  726.    count = LZXtable_two[temp = symbol & 31];
  727.    temp = LZXtable_one[temp];
  728.    if((temp >= 3) && (decr->decrunch_method == 3))
  729.    {
  730.     temp -= 3;
  731.     count += ((control & LZXmask_bits[temp]) << 3);
  732.     control >>= temp;
  733.     if((shift -= temp) < 0)
  734.     {
  735.      shift += 16;
  736.      control += *source++ << (8 + shift);
  737.      control += *source++ << shift;
  738.     }
  739.     count += (temp = decr->offset_table[control & 127]);
  740.     temp = decr->offset_len[temp];
  741.    }
  742.    else
  743.    {
  744.     count += control & LZXmask_bits[temp];
  745.     if(!count) count = decr->last_offset;
  746.    }
  747.    control >>= temp;
  748.    if((shift -= temp) < 0)
  749.    {
  750.     shift += 16;
  751.     control += *source++ << (8 + shift);
  752.     control += *source++ << shift;
  753.    }
  754.    decr->last_offset = count;
  755.  
  756.    count = LZXtable_two[temp = (symbol >> 5) & 15] + 3;
  757.    temp = LZXtable_one[temp];
  758.    count += (control & LZXmask_bits[temp]);
  759.    control >>= temp;
  760.    if((shift -= temp) < 0)
  761.    {
  762.     shift += 16;
  763.     control += *source++ << (8 + shift);
  764.     control += *source++ << shift;
  765.    }
  766.    string = (decr->decrunch_buffer + decr->last_offset < destination) ?
  767.             destination - decr->last_offset : destination + 65536 - decr->last_offset;
  768.    do
  769.    {
  770.     *destination++ = *string++;
  771.    } while(--count);
  772.   }
  773.  } while((destination < decr->destination_end) && (source < decr->source_end));
  774.  
  775.  decr->control = control;
  776.  decr->shift = shift;
  777.  decr->source = source;
  778.  decr->destination = destination;
  779. }
  780.  
  781. /* ---------------------------------------------------------------------- */
  782.  
  783. static LONG LZXextract(struct xadArchiveInfo *ai, struct xadMasterBase *xadMasterBase,
  784. ULONG unpack_size, ULONG rescrc)
  785. {
  786.   UBYTE *temp;
  787.   ULONG count, crc = ~0;
  788.   LONG err;
  789.   struct LZXDecrData *decr;
  790.  
  791.   decr = (struct LZXDecrData *) ai->xai_PrivateClient;
  792.  
  793.   while(unpack_size > 0)
  794.   {
  795.     if(decr->pos == decr->destination) /* time to fill the buffer? */
  796.     {
  797.       /* check if we have enough data and read some if not */
  798.       if(decr->source >= decr->source_end) /* have we exhausted the current read buffer? */
  799.       {
  800.         temp = decr->read_buffer;
  801.         if((count = temp - decr->source + 16384))
  802.         {
  803.           do /* copy the remaining overrun to the start of the buffer */
  804.           {
  805.             *temp++ = *(decr->source++);
  806.           } while(--count);
  807.         }
  808.         decr->source = decr->read_buffer;
  809.         count = decr->source - temp + 16384;
  810.  
  811.         if(decr->pack_size < count)
  812.           count = decr->pack_size; /* make sure we don't read too much */
  813.  
  814.         if((err = xadHookAccess(XADAC_READ, count, temp, ai)))
  815.           return err;
  816.         decr->pack_size -= count;
  817.  
  818.         temp += count;
  819.         if(decr->source >= temp)
  820.           return XADERR_DECRUNCH; /* argh! no more data! */
  821.       } /* if(decr->source >= decr->source_end) */
  822.  
  823.     /* check if we need to read the tables */
  824.     if(decr->decrunch_length <= 0)
  825.     {
  826.       if(LZX_read_literal_table(decr))
  827.         return XADERR_DECRUNCH; /* argh! can't make huffman tables! */
  828.     }
  829.  
  830.     /* unpack some data */
  831.     if(decr->destination >= decr->decrunch_buffer + 258 + 65536)
  832.     {
  833.       if((count = decr->destination - decr->decrunch_buffer - 65536))
  834.       {
  835.         temp = (decr->destination = decr->decrunch_buffer) + 65536;
  836.         do /* copy the overrun to the start of the buffer */
  837.         {
  838.           *(decr->destination++) = *temp++;
  839.         } while(--count);
  840.       }
  841.       decr->pos = decr->destination;
  842.     }
  843.     decr->destination_end = decr->destination + decr->decrunch_length;
  844.     if(decr->destination_end > decr->decrunch_buffer + 258 + 65536)
  845.       decr->destination_end = decr->decrunch_buffer + 258 + 65536;
  846.     temp = decr->destination;
  847.  
  848.     LZXdecrunch(decr);
  849.  
  850.     decr->decrunch_length -= (decr->destination - temp);
  851.    }
  852.  
  853. /* calculate amount of data we can use before we need to fill the buffer again */
  854.    count = decr->destination - decr->pos;
  855.    if(count > unpack_size)
  856.      count = unpack_size; /* take only what we need */
  857.  
  858.    if(rescrc) /* when no CRC given, then skip writing */
  859.    {
  860.      crc = xadCalcCRC32(XADCRC32_ID1, crc, count, decr->pos);
  861.      if((err = xadHookAccess(XADAC_WRITE, count, decr->pos, ai)))
  862.        return err;
  863.    }
  864.    unpack_size -= count;
  865.    decr->pos += count;
  866.    decr->DataPos += count;
  867.  }
  868.  
  869.  if(rescrc && ~crc != rescrc)
  870.    return XADERR_CHECKSUM;
  871.  
  872.  return 0;
  873. }
  874.  
  875. /* ---------------------------------------------------------------------- */
  876.  
  877. ASM(LONG) LZX_UnArchive(REG(a0, struct xadArchiveInfo *ai),
  878. REG(a6, struct xadMasterBase *xadMasterBase))
  879. {
  880.   struct xadFileInfo *fi;
  881.   struct LZXDecrData *decr = 0;
  882.   LONG ret = 0, i;
  883.   ULONG crc = ~0;
  884.  
  885.   fi = ai->xai_CurFile;
  886.   if(!ai->xai_PrivateClient || LZXDD(ai)->ArchivePos != LZXPE(fi)->ArchivePos
  887.   || LZXDD(ai)->DataPos > LZXPE(fi)->DataStart)
  888.   {
  889.     if(ai->xai_PrivateClient) /* free the unneeded data */
  890.     {
  891.       xadFreeObjectA(ai->xai_PrivateClient, 0);
  892.       ai->xai_PrivateClient = 0;
  893.     }
  894.     if((i = LZXPE(fi)->ArchivePos - ai->xai_InPos))
  895.     {
  896.       if((ret = xadHookAccess(XADAC_INPUTSEEK, i, 0, ai)))
  897.         return ret;
  898.     }
  899.   }
  900.  
  901.   switch(LZXPE(fi)->PackMode)
  902.   {
  903.   case LZXHDR_PACK_STORE:
  904.     if(!(ret = xadHookTagAccess(XADAC_COPY, fi->xfi_Size, 0, ai, XAD_GETCRC32, &crc, TAG_DONE)) && ~crc != LZXPE(fi)->CRC)
  905.       ret = XADERR_CHECKSUM;
  906.     break;
  907.   case LZXHDR_PACK_NORMAL:
  908.     if(!ai->xai_PrivateClient && !(decr = (struct LZXDecrData *)
  909.     xadAllocVec(sizeof(struct LZXDecrData), MEMF_PUBLIC|MEMF_CLEAR)))
  910.       ret = XADERR_NOMEMORY;
  911.     else
  912.     {
  913.       if(decr)
  914.       {
  915.         decr->ArchivePos = LZXPE(fi)->ArchivePos;
  916.         decr->DataPos = 0;
  917.         decr->shift = -16;
  918.         decr->last_offset = 1;
  919.         decr->source_end = (decr->source = decr->read_buffer + 16384) - 1024;
  920.         decr->pos = decr->destination_end = decr->destination = decr->decrunch_buffer + 258 + 65536;
  921.         decr->pack_size = fi->xfi_Flags & XADFIF_GROUPED ?
  922.         fi->xfi_GroupCrSize : fi->xfi_CrunchSize;
  923.         ai->xai_PrivateClient = decr;
  924.       }
  925.  
  926.       if((i = LZXPE(fi)->DataStart - LZXDD(ai)->DataPos))
  927.     ret = LZXextract(ai, xadMasterBase, i, 0);
  928.     
  929.       if(!ret)
  930.     ret = LZXextract(ai, xadMasterBase, fi->xfi_Size, LZXPE(fi)->CRC);
  931.  
  932.       /* free no longer needed temporary buffer and stuff structure */
  933.       if(ret || !(fi->xfi_Flags & XADFIF_GROUPED) || (fi->xfi_Flags & XADFIF_ENDOFGROUP))
  934.       {
  935.         xadFreeObjectA(ai->xai_PrivateClient, 0);
  936.         ai->xai_PrivateClient = 0;
  937.       }
  938.     }
  939.     break;
  940.   default: ret = XADERR_DECRUNCH; break;
  941.   }
  942.  
  943.   return ret;
  944. }
  945.  
  946. ASM(void) LZX_Free(REG(a0, struct xadArchiveInfo *ai),
  947. REG(a6, struct xadMasterBase *xadMasterBase))
  948. {
  949.   if(ai->xai_PrivateClient) /* decrunch buffer */
  950.   {
  951.     xadFreeObjectA(ai->xai_PrivateClient, 0);
  952.     ai->xai_PrivateClient = 0;
  953.   }
  954. }
  955.  
  956. const struct xadClient LZX_Client = {
  957. NEXTCLIENT, XADCLIENT_VERSION, XADMASTERVERSION, LZX_VERSION, LZX_REVISION,
  958. 10, XADCF_FILEARCHIVER|XADCF_FREEFILEINFO, XADCID_LZX, "LZX",
  959. (BOOL (*)()) LZX_RecogData, (LONG (*)()) LZX_GetInfo,
  960. (LONG (*)()) LZX_UnArchive, (void (*)()) LZX_Free};
  961.  
  962. #endif /* XADMASTER_LZX_C */
  963.